import { Input as TaroInput, View } from '@tarojs/components';
import theme from '@/theme';
import { ComponentProps, useEffect, useState } from 'react';
import './index.scss';
import classNames from 'classnames';
import { Icon } from 'pd-taro-ui';
import { inputNumberParser, inputNumberFormatter, isValidNumber } from './utils';

export interface InputNumberProps {
  placeholder?: string;
  /** 默认number类型， 根据stringMode判断 */
  value?: number | undefined;
  onChange?: (value: InputNumberProps['value']) => void;
  onBlur?: any;
  staticed?: boolean;
  disabled?: boolean;
  compProps?: ComponentProps<typeof TaroInput>;
  clearable?: boolean;
  className?: string;
  /** 前缀 */
  renderPrefix?: any;
  prefixClassName?: string;
  /** 后缀 */
  renderSuffix?: any;
  suffixClassName?: string;

  /** 最小值 */
  min?: number;
  /** 最大值 */
  max?: number;
  /** 每次点击改变的间隔大小 */
  step?: number;
  /** 是否禁止输入，但不禁止点击按钮 */
  disabledInput?: boolean;
  /** 数值精度(小数点后几位)，默认不限制。 配置 formatter 时会以 formatter 为准 */
  precision?: number;
  /** 指定从 formatter 里转换回数字的方式，和 formatter 搭配使用	 */
  parser?: (value: string | undefined, options?: inputNumberFormatterProps) => number | undefined;
  /** 指定输入框展示值的格式 */
  formatter?: (value: number | string | undefined, options?: inputNumberFormatterProps) => string;
}

export type inputNumberFormatterProps = Pick<InputNumberProps, 'min' | 'max' | 'step' | 'precision'> & {};

/** 数字录入框 */
const InputNumber = (props: InputNumberProps) => {
  const {
    onChange,
    value,
    disabled,
    staticed,
    onBlur,
    clearable = false,
    placeholder,
    className,
    compProps,
    min,
    max,
    step,
    precision,
    parser = inputNumberParser,
    formatter = inputNumberFormatter,
    renderPrefix,
    renderSuffix,
    prefixClassName,
    suffixClassName,
  } = props;
  let type = compProps?.type || 'digit';
  if (process.env.TARO_ENV === 'h5') type = 'text'; // 处理h5不支持录入普通字符
  const [hover, setHover] = useState(false);
  const [innerValue, setInnerValue] = useState<string | undefined>('');

  useEffect(() => {
    if (hover) return;
    const val = formatter?.(value, {
      min,
      max,
      step,
      precision,
    });
    // console.log('inputNumber useEffect', { value, val, innerValue });
    if (val !== innerValue) {
      setInnerValue(val);
    }
  }, [formatter, hover, innerValue, max, min, precision, step, value]);

  const getNumValue = (val: string) => {
    if (!val) {
      return undefined;
    }
    let num = parser?.(val, {
      min,
      max,
      step,
      precision,
    });
    if (!isValidNumber(num)) return undefined;
    if (typeof num !== 'number') {
      return undefined;
    }
    if (typeof min === 'number' && min > num) {
      num = min;
    }
    if (typeof max === 'number' && max < num) {
      num = max;
    }

    return num;
  };

  const handleChange = (val: any) => {
    setInnerValue(val);
    onChange?.(getNumValue(val));
  };

  if (staticed) {
    return <View className='pd-inputNumber--static'>{innerValue}</View>;
  }
  return (
    <View
      className={classNames({ 'pd-inputNumber': true, 'pd-inputNumber--disabled': disabled, 'pd-inputNumber--hover': hover }, className)}>
      {!!renderPrefix && <View className={classNames('pd-inputNumber__prefix', prefixClassName)}>{renderPrefix}</View>}
      <TaroInput
        className='pd-inputNumber__inner'
        value={innerValue}
        disabled={disabled}
        placeholder={placeholder}
        {...compProps}
        type={type}
        onInput={e => handleChange(e.detail.value)}
        onFocus={e => {
          setHover(true);
          compProps?.onFocus?.(e);
        }}
        onBlur={e => {
          setHover(false);
          onBlur?.(e);
        }}
      />
      {!!renderSuffix && <View className={classNames('pd-inputNumber__suffix', suffixClassName)}>{renderSuffix}</View>}
      {clearable && !disabled && !!value && <Icon name='error' size={36} color='#bbb' onClick={() => onChange?.(undefined)} />}
    </View>
  );
};
export default InputNumber;
